def STRING(required=False, minLength=1, maxLength=256, default='', doc=None):
    def f(param):
        if required:
            return _check_required(param)
        if not isinstance(param, str):
            return param, _error(param, 'validation.param_is_not_text')
        length = len(param)
        if not (length >= minLength and length <= maxLength):
            return _get_return_value(required, param, default),\
                   _error(param, 'validation.incorrect_length')
        return _get_return_value(required, param, default)
    f.__json__ = {'type': 'string',
                  'required': required,
                  'minLength': minLength,
                  'maxLength': maxLength}
    if doc is not None:
        f.__json__.update({'doc': doc})
    return f


def INTEGER(required=False, minimum=0, maximum=10):
    def f(param):
        if required:
            return _check_required(param)
        if isinstance(param, (int, long)):
            return param, _error(param, 'validation.param_is_not_number')
        if not (long(param) >= minimum and long(param) <= maximum):
            return param, _error(param, 'validation.number_out_of_range',
                                 'min={}, max={}'.format(minimum, maximum))
        return param
    f.__json__ = {'type': 'integer',
                  'required': required,
                  'minimum': minimum,
                  'maximum': maximum}
    return f


def BOOLEAN(required=False):
    def f(param):
        if required:
            return _check_required(param)
        return param
    f.__json__ = {'type': 'integer',
                  'required': required}
    return f


def _check_required(param):
    if param is None:
        return param, _error(param, 'validation.mandatory_param')


def _get_return_value(required, param, default):
    if required and param is None:
        return default
    else:
        return param


def _error(param, code, additionalText=''):
    return {'param': param,
            'code': code,
            'text': _('business.{0}'.format(code)) + additionalText}
